#ifndef __UTILS_H__
#define __UTILS_H__

#include <cassert>
#include <string>
#include <iostream>
#include <type_traits> // std::move

#include <vector>
#include <Eigen/Dense>

std::vector<double> _grad(const std::vector<double>&in, double dt=1.) 
{
  auto M = in.size();
  assert(M >= 3);
  std::vector<double> out(M);

  out[0] = (in[1]-in[0])/dt;
  out[M-1] = (in[M-1]-in[M-2])/dt;

  for (int i = 1; i < M-2; i++) {
    out[i] = (in[i+1]-in[i-1]) / (2*dt);
  }

  return std::move(out);
}

Eigen::VectorXd _grad(const Eigen::VectorXd&in, double dt=1.) 
{
  auto M = in.size();
  assert(M >= 3);

  Eigen::VectorXd out(M);

  out[0] = (in[1]-in[0])/dt;
  out[M-1] = (in[M-1]-in[M-2])/dt;
  for (int i = 1; i < M-2; i++) {
    out[i] = (in[i+1]-in[i-1]) / (2*dt);
  }

  return std::move(out);
}

#endif
